package com.kx.file.util;

import com.madgag.gif.fmsware.AnimatedGifEncoder;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;

/**
 * 生成Gif的工具类
 *
 * @Author Sun
 * @Date 2021/7/22 21:34
 */
public class GifUtil {
    /**
     * 定义每隔多少帧取一帧（步长）
     */
    private static final Integer DEFAULT_MARGIN = 2;
    /**
     * 定义默认的帧频率
     */
    private static final Integer DEFAULT_FRAME_RATE = 10;

    /**
     * 定义指定一个视频，生成gif与jpg的方法
     *
     * @param filePath   原视频文件的位置
     * @param startFrame 起始帧的位置
     * @param frameCount 截帧的总帧数
     * @param frameRate  帧频率
     * @param margin     步长
     */
    public static void buildGifAndJpg(String filePath, int startFrame, int frameCount, Integer frameRate, Integer margin) {
        try {
            if (frameRate == null) {
                frameRate = DEFAULT_FRAME_RATE;
            }
            if (margin == null) {
                margin = DEFAULT_MARGIN;
            }
            //gif存储的路径
            //文件路径，文件名不变，后缀改为gif
            String gifPath = filePath.substring(0, filePath.lastIndexOf(".")) + ".gif";
            //文件输出流
            FileOutputStream targetFile = new FileOutputStream(gifPath);
            //获取视频文件
            //使用ffmpeg引擎逐帧读取
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(filePath);
            //创建一个java2d画面的转换器
            Java2DFrameConverter converter = new Java2DFrameConverter();
            //让ffmpeg引擎开始工作
            ff.start();

            //读取视频的总帧数
            Integer videoLength = ff.getLengthInFrames();


            //万一视频的总帧数不够用怎么办？
            if (startFrame > videoLength || (startFrame + frameCount * margin) > videoLength) {
                //视频总帧数不够用
                startFrame = 1;
                frameCount = (videoLength - startFrame - margin) / margin;
            }
            //现在总帧数一定是够用的了
            //设置ffmpeg加载的位置
            ff.setFrameNumber(startFrame);

            //实例化一个gif的编码器
            AnimatedGifEncoder en = new AnimatedGifEncoder();
            //给gif设置帧频率
            en.setFrameRate(frameRate);

            //设置gif无限循环
            en.setRepeat(0);

            //让gif对目标gif文件进行编码
            en.start(targetFile);


            //设置生成图片的标志位
            boolean poster = false;

            //逐帧：
            for (int i = 0; i < frameCount; i++) {
                if (!poster) {
                    //读取一帧转化为图片
                    Frame f = ff.grabFrame();
                    if (f != null) {
                        String jpgPath = filePath.substring(0, filePath.lastIndexOf(".")) + ".jpg";
                        File jpgFile = new File(jpgPath);
                        //获取图片信息
                        BufferedImage bufferedImage = converter.getBufferedImage(f);
                        //把图片数据写入到文件上
                        ImageIO.write(bufferedImage, "jpg", jpgFile);
                        poster = true;
                    }
                }
                //取出一帧用于合成gif
                en.addFrame(converter.convert(ff.grabFrame()));
                //设置下一帧的位置
                ff.setFrameNumber(ff.getFrameNumber() + margin);
            }
            en.finish();
            ff.stop();
            ff.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        buildGifAndJpg("C:\\Users\\孙晋超\\Pictures\\Saved Pictures\\1.mp4",5,50,10,10);
    }
}
